#include "StdAfx.h"
#include "CameraEventsHandler.h"


CameraEventsHandler::CameraEventsHandler(Ogre::Camera *camera)
	:mCamera(camera),
	mTopSpeed(150), 
	mVelocity(Ogre::Vector3::ZERO),
	mGoingForward(false),
	mGoingBack(false),
	mGoingLeft(false),
	mGoingRight(false),
	mGoingUp(false),
	mGoingDown(false),
	mFastMove(false),
	rightButtonPressed(false),
	leftButtonPressed(false)
{
	mCamera->setAutoTracking(false);
	mCamera->setFixedYawAxis(true);
}


CameraEventsHandler::~CameraEventsHandler(void)
{
}

bool CameraEventsHandler::frameRenderingQueued(const Ogre::FrameEvent& evt)
{
	// build our acceleration vector based on keyboard input composite
	Ogre::Vector3 accel = Ogre::Vector3::ZERO;
	if (mGoingForward) accel += mCamera->getDirection();
	if (mGoingBack) accel -= mCamera->getDirection();
	if (mGoingRight) accel += mCamera->getRight();
	if (mGoingLeft) accel -= mCamera->getRight();
	if (mGoingUp) accel += mCamera->getUp();
	if (mGoingDown) accel -= mCamera->getUp();

	// if accelerating, try to reach top speed in a certain time
	Ogre::Real topSpeed = mFastMove ? mTopSpeed * 20 : mTopSpeed;
	if (accel.squaredLength() != 0)
	{
		accel.normalise();
		mVelocity += accel * topSpeed * evt.timeSinceLastFrame * 10;
	}
	// if not accelerating, try to stop in a certain time
	else mVelocity -= mVelocity * evt.timeSinceLastFrame * 10;

	Ogre::Real tooSmall = std::numeric_limits<Ogre::Real>::epsilon();

	// keep camera velocity below top speed and above epsilon
	if (mVelocity.squaredLength() > topSpeed * topSpeed)
	{
		mVelocity.normalise();
		mVelocity *= topSpeed;
	}
	else if (mVelocity.squaredLength() < tooSmall * tooSmall)
		mVelocity = Ogre::Vector3::ZERO;

	if (mVelocity != Ogre::Vector3::ZERO) mCamera->move(mVelocity * evt.timeSinceLastFrame);

	return true;
}

void CameraEventsHandler::keyPressEvent(QKeyEvent *e)
{
	if(rightButtonPressed)
	{
		if (e->key() == Qt::Key_Up) mGoingForward = true;
		else if (e->key() == Qt::Key_Down) mGoingBack = true;
		else if (e->key() == Qt::Key_Left) mGoingLeft = true;
		else if (e->key() == Qt::Key_Right) mGoingRight = true;
		else if (e->key() == Qt::Key_PageUp) mGoingUp = true;
		else if (e->key() == Qt::Key_PageDown) mGoingDown = true;
		else if (e->key() == Qt::Key_Shift) mFastMove = true;
	}
}

void CameraEventsHandler::keyReleaseEvent(QKeyEvent* e)
{
	if (e->key() == Qt::Key_Up) mGoingForward = false;
	else if (e->key() == Qt::Key_Down) mGoingBack = false;
	else if (e->key() == Qt::Key_Left) mGoingLeft = false;
	else if (e->key() == Qt::Key_Right) mGoingRight = false;
	else if (e->key() == Qt::Key_PageUp) mGoingUp = false;
	else if (e->key() == Qt::Key_PageDown) mGoingDown = false;
	else if (e->key() == Qt::Key_Shift) mFastMove = false;
}

void CameraEventsHandler::mousePressEvent(QMouseEvent *e)
{
	if(e->buttons().testFlag(Qt::RightButton))
	{
		rightButtonPressed = true;
		clickPos = e->pos();
	}
}

void CameraEventsHandler::mouseMoveEvent(QMouseEvent *e)
{
	if(e->buttons().testFlag(Qt::RightButton))
	{
		const QPoint& currentPos = e->pos();
		Ogre::Real deltaX = currentPos.x() - clickPos.x();
		Ogre::Real deltaY = currentPos.y() - clickPos.y();

		mCamera->yaw(Ogre::Degree(-deltaX * 0.15f));
		mCamera->pitch(Ogre::Degree(-deltaY * 0.15f));

		clickPos = currentPos;
	}
}

void CameraEventsHandler::mouseReleaseEvent(QMouseEvent *e)
{
		rightButtonPressed = false;
		leftButtonPressed = false;
}

void CameraEventsHandler::wheelEvent(QWheelEvent *e)
{
}

void CameraEventsHandler::setAspectRatio(Ogre::Real aspectRatio)
{
	mCamera->setAspectRatio(aspectRatio);
}